

let cfg = require('./utils/cfg');

class EE{
    constructor(eventName,func,context,once){
        this.eventName = eventName;
        this.func = func;
        this.context = context;
        this.bOnce = once;

        this.bExpired = false;
    }

    isExpired(){
        return this.bExpired;
    }

    setExpired(value){
        this.bExpired = value;
    }

    dispatch(params){
        this.func.apply(this.context,params);
        if(this.bOnce){
            this.bExpired = true;
        }
    }
}

class EventEmitter{

    constructor(){
        this.__events = {};
        this.__tmp = {
            lst:null,
            bDispathing:false
        };
    }

    _beforeDispath(lst){
        this.__tmp.lst = lst;
        this.__tmp.bDispathing = true;
    }

    _afterDispath(){
        this.__tmp.lst = null;
        this.__tmp.bDispathing = false;
    }

    _inDispathing(lst){
       return this.__tmp.bDispathing && this.__tmp.lst === lst;
    }

    on(eventName,func,context){
        this._addEventListener(eventName,func,context,false);
    }

    once(eventName,func,context){
        this._addEventListener(eventName,func,context,true);
    }

    off(eventName,func,context){
        let lst =  this.__events[eventName];
        if(lst && lst.length > 0){
            let idx = -1;
            let ee = lst.find((item,eeIdx)=>{
                idx = eeIdx;
                return item.context === context && item.func === func;
            });
            if(ee){
                if(this._inDispathing(lst)){
                    ee.setExpired(true);
                }else{
                    lst.splice(idx,1);
                }
            }else{
                console.warn(`cannot find ee! 没用注册?`);
            }
        }
    }

    emit(eventName){
        let lst = this.__events[eventName];
        if(lst && lst.length > 0){

            let params;
            if(arguments.length > 1){
                params = Array.prototype.slice.call(arguments,1);
            }else{
                params = [];
            }

            this._beforeDispath(lst);
            lst.forEach(ee=>{
                if(!ee.isExpired()){
                    ee.dispatch(params);
                }
            });
            this._afterDispath();

            // 删除掉过期的
            this.__events[eventName] = lst.filter(ee=>{
                return !ee.isExpired();
            });
        }
    }


    _checkListenerCount(eventName,lst){
        if(cfg.Debug){
            if(lst.length >= 5){
                console.warn(`eventName:${eventName} 监听器过多!`);
            }
        }
    }

    _addEventListener(eventName,func,context,params,once){

        let ee = new EE(eventName,func,context,once);

        let lst = this.__events[eventName];
        if(lst){
            lst.push(ee);
            this._checkListenerCount(eventName,lst);
        }else{
            this.__events[eventName] = [];
            this.__events[eventName].push(ee);
            this._checkListenerCount(eventName,this.__events[eventName]);
        }
    }
}


module.exports = EventEmitter;
